import { memo, useEffect, useState } from 'react'
import { Drawer, Tree, Menu, Dropdown, Button, Space } from 'antd';
import { UpOutlined } from '@ant-design/icons';

import { postForm, postJson } from '@/utils/http/linitly.request.js'
import { warnPrompt, successPrompt } from '@/utils/default.prompt'

const Empower = ({
  visible,
  close,
  roleId
}) => {

  const [ permissions, setPermissions ] = useState([])
  const [ expandedKeys, setExpandedKeys ] = useState([])                // 展开的树节点
  const [ checkedKeys, setCheckedKeys ] = useState([]);                 // 选中复选框的树节点
  const [ halfCheckedKeys, setHalfCheckedKeys ] = useState([])          // 半选复选框的树节点
  const [ autoExpandParent, setAutoExpandParent ] = useState(true);     // 自动展开父节点

  const [ saveButtonLoading, setSaveButtonLoading ] = useState(false)   // 保存按钮loading
  const [ saveAndCloseButtonLoading, setSaveAndCloseButtonLoading ] = useState(false)

  useEffect(() => {
    roleId && getPermissions()
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [roleId])

  const menu = (
    <Menu onClick={handleMenuClick}>
      <Menu.Item key="1">
        全部勾选
      </Menu.Item>
      <Menu.Item key="2">
        取消全选
      </Menu.Item>
      <Menu.Item key="3">
        展开所有
      </Menu.Item>
      <Menu.Item key="4">
        合并所有
      </Menu.Item>
    </Menu>
  )
  const footer = (
    <>
      <div>
        <Dropdown overlay={menu}>
          <Button>
            权限树操作 <UpOutlined />
          </Button>
        </Dropdown>
      </div>
      <Space>
        <Button onClick={close}>取消</Button>
        <Button type="primary" ghost onClick={empower(false)} loading={saveButtonLoading}>仅保存</Button>
        <Button type="primary" loading={saveAndCloseButtonLoading} onClick={empower(true)}>保存并关闭</Button>
      </Space>
    </>
  )

  return (
    <Drawer title="编辑角色权限" placement="right" onClose={close} visible={visible} width={550} footer={footer}
    footerStyle={{ display: 'flex', justifyContent: 'space-between' }}>
      <Tree
        checkable
        expandedKeys={expandedKeys}
        onExpand={expand}
        checkedKeys={checkedKeys}
        onCheck={check}
        treeData={permissions}
        autoExpandParent={autoExpandParent}
      />
    </Drawer>
  )

  // 获取所有的权限信息并且将对应的值赋值到树型控件中
  function getPermissions() {
    postForm('/sysRole/tree', {
      roleId
    }).then((res) => {
      let expandedKeys = []
      let checkedKeys = []
      const treeDatas = res.map(value => transform(value, expandedKeys, checkedKeys))
      setPermissions(treeDatas)
      setExpandedKeys(expandedKeys)
      setCheckedKeys(checkedKeys)
    })
  }

  function transform(value, expandedKeys, checkedKeys) {
    // 如果权限信息有子权限或者子菜单，默认添加到展开的数组中，也就是父节点添加进去(默认父节点展开)
    // 如果不是子节点，并且是选中的，那么就添加到选中节点数组中，父节点的选中会自动计算
    if (value.childs || value.functionPermissions) {
      expandedKeys.push(getTreeKey(value))
    } else if (value.selected === 1) {
      checkedKeys.push(getTreeKey(value))
    }
    return {
      key: getTreeKey(value),
      title: value.name,
      children: value.childs ? value.childs.map(data => transform(data, expandedKeys, checkedKeys)) :
                value.functionPermissions ? value.functionPermissions.map(data => transform(data, expandedKeys, checkedKeys)) : []
                ,
      selectable: false       // 设置让节点无法选择，选中节点文字可以直接切换复选框的选择
    }
  }

  // 根据后端返回的数据设置树型控件单项的key，方便后续保存时区别权限类型
  function getTreeKey(value) {
    return value.id + '-' + value.type
  }

  // 展开/收起节点时处理函数
  function expand(expandedKeys) {
    setExpandedKeys(expandedKeys);
    setAutoExpandParent(false);
  }

  // 点击复选框的处理函数
  function check(checkedKeys, {halfCheckedKeys}) {
    setCheckedKeys(checkedKeys)
    setHalfCheckedKeys(halfCheckedKeys)
  }

  // 权限树操作的菜单选项点击处理函数
  function handleMenuClick(e) {
    switch (e.key) {
      case '1':
        // 全部勾选
        const allKeys = getAllKeysByTreeData(permissions)
        setCheckedKeys(allKeys)
        break;
      case '2':
        // 取消勾选
        setCheckedKeys([])
        break;
      case '3':
        // 展开所有
        const allExpandKeys = getAllExpandKeysByTreeData(permissions)
        setExpandedKeys(allExpandKeys)
        break;
      case '4':
        // 合并所有
        setExpandedKeys([])
        break;
      default:
        break;
    }
  }

  // 通过所有的树数据获取所有的节点key
  function getAllKeysByTreeData(treeData, allKeys) {
    if (!allKeys) allKeys = []
    for (let i = 0; i < treeData.length; i++) {
      const e = treeData[i];
      if (e.children && e.children.length > 1) {
        getAllKeysByTreeData(e.children, allKeys)
        continue
      }
      allKeys.push(e.key)
    }
    return allKeys
  }

  // 通过所有的树数据获取所有的父节点key
  function getAllExpandKeysByTreeData(treeData, allExpandKeys) {
    if (!allExpandKeys) allExpandKeys = []
    for (let i = 0; i < treeData.length; i++) {
      const e = treeData[i];
      if (e.children && e.children.length > 0) {
        allExpandKeys.push(e.key)
        getAllExpandKeysByTreeData(e.children, allExpandKeys)
      }
    }
    return allExpandKeys
  }

  // 修改权限
  function empower(saveAndClose) {
    return function() {
      // 如果选中的复选框是空的，需要提示用户，不建议这样设置
      if (checkedKeys.length < 1) {
        warnPrompt('未选中权限，请点击选择')
        return
      }
      // 遍历选中的复选框key和半选复选框key数组，获取相关的所有菜单权限和功能权限
      let sysMenuIds = []
      let functionPermissionIds = []
      checkedKeys.forEach(key => { setMenuAndFunctionPermissionIdByTreeKey(key, sysMenuIds, functionPermissionIds) })
      halfCheckedKeys.forEach(key => { setMenuAndFunctionPermissionIdByTreeKey(key, sysMenuIds, functionPermissionIds) })
      // 如果选择的菜单或者权限为空，提示用户，一般不会触发
      if (sysMenuIds.length < 1) {
        warnPrompt('未选中菜单，请点击选择')
        return
      }
      if (functionPermissionIds.length < 1) {
        warnPrompt('未选中权限，请点击选择')
        return
      }
      saveAndClose ? setSaveAndCloseButtonLoading(true) : setSaveButtonLoading(true)
      postJson('/sysRole/empower', {
        id: roleId,
        sysMenuIds,
        functionPermissionIds
      }).then(() => {
        successPrompt('为角色赋权成功')
      }).finally(() => {
        saveAndClose ? setSaveAndCloseButtonLoading(false) : setSaveButtonLoading(false)
        // 如果是保存并关闭，则调用抽屉的关闭方法
        saveAndClose && close()
      })
    }
  }

  // 根据树型控件的key获取菜单和功能权限的ID
  function setMenuAndFunctionPermissionIdByTreeKey(key, sysMenuIds, functionPermissionIds) {
    const idAndType = key.split('-')
    // 类型为1是菜单，为2是功能权限
    if (idAndType[1] === '1') {
      sysMenuIds.push(idAndType[0])
    } else if (idAndType[1] === '2') {
      functionPermissionIds.push(idAndType[0])
    }
  }
}

export default memo(Empower)
